package com.cocotingo.snail.template.models;

import java.util.Iterator;

import com.cocotingo.snail.template.TemplateSyntaxException;


public abstract class Node {
	
	static final Iterable<Node> EMPTY_ITERABLE = new Iterable<Node>() {
		@Override
		public Iterator<Node> iterator() {
			return new Iterator<Node>() {
				@Override
				public boolean hasNext() {
					return false;
				}
				@Override
				public Node next() {
					return null;
				}
				@Override
				public void remove() {
					throw new UnsupportedOperationException();
				}
			};
		}
	};
	
	public abstract void validateNode() throws TemplateSyntaxException;
	
	public void validate() throws TemplateSyntaxException {
		this.validateNode();
		for (Node node : this.children()) {
			node.validate();
		}
	}
	
	public abstract Iterable<Node> children();
	
	public void printNodeHierarchy() {
		printNodeHierarchy(this, 0);
	}
	
	private static void printNodeHierarchy(Node node, int tab) {
		for (int i = 0; i < tab; i++) System.out.print('\t');
		System.out.println(node);
		tab++;
		for (Node n : node.children()) {
			printNodeHierarchy(n, tab);
		}
	}
	
	@Override
	public String toString() {
		String attrs = getXMLAttributes();
		if (attrs == null) {
			return String.format("[%s]", getXMLNodeName());
		} else {
			return String.format("[%s %s]", getXMLNodeName(), attrs);
		}
	}
	
	protected abstract String getXMLNodeName();
	protected abstract String getXMLAttributes();
	
	public String getXMLStartTag() {
		String attrs = getXMLAttributes();
		if (attrs == null || attrs.isEmpty()) {
			return String.format("<%s>", getXMLNodeName());
		} else {
			return String.format("<%s %s>", getXMLNodeName(), attrs);
		}
	}
	
	public String getXMLEndTag() {
		return String.format("</%s>", getXMLNodeName());
	}
	
}
